package mil.af.amc.adpetracker.dao.hibernate;

import mil.af.amc.adpetracker.dao.AdpeAccountDao;
import mil.af.amc.adpetracker.model.AdpeAccount;
import mil.af.amc.adpetracker.model.EquipmentItem;
import mil.af.amc.adpetracker.model.User;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.List;

/**
 * Hibernate specific DAO implementation for ADPE Account objects
 *
 * @author TSgt Jason Ferguson
 */
@Repository("adpeAccountDao")
public class HibernateAdpeAccountDao extends HibernateGenericDao<AdpeAccount> implements AdpeAccountDao {

    private static final Log log = LogFactory.getLog(HibernateAdpeAccountDao.class);

    public HibernateAdpeAccountDao() {
        super(AdpeAccount.class);
    }

    public HibernateAdpeAccountDao(Class<AdpeAccount> type) {
        super(type);
    }

    public int getEquipmentItemCount(AdpeAccount account) {

        Criteria aaCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        aaCriteria.setProjection(Projections.rowCount());
        aaCriteria.add(Restrictions.eq("account", account));

        Integer result = null;
        try {
            result = (Integer) aaCriteria.uniqueResult();
        } catch (HibernateException e) {
            log.debug("getEquipmentItemCount threw HibernateException", e);
        }

        return result;

//        DetachedCriteria crit = DetachedCriteria.forClass(EquipmentItem.class);
//        crit.setProjection(Projections.rowCount());
//        crit.add(Restrictions.eq("account", account));
//        return (Integer) getHibernateTemplate().findByCriteria(crit).get(0);

    }

    public BigDecimal getAccountValue(final AdpeAccount account) {

        Criteria aaCriteria = sessionFactory.getCurrentSession().createCriteria(EquipmentItem.class);
        aaCriteria.add(Restrictions.eq("account", account));
        aaCriteria.setProjection(Projections.sum("originalCost"));
        aaCriteria.add(Restrictions.isNull("drmoPackage"));
        aaCriteria.add(Restrictions.isNull("rosPackage"));

        return (BigDecimal) aaCriteria.uniqueResult();

//        return (Double) getHibernateTemplate().execute(new HibernateCallback() {
//            public Object doInHibernate(Session session) throws HibernateException, SQLException {
//
//                Criteria aaCriteria = session.createCriteria(EquipmentItem.class);
//
//
//            }
//        });

    }

    @SuppressWarnings({"unchecked"})
    public List<AdpeAccount> getAccountsByUser(final User user) {

        Criteria primaryAaCriteria = sessionFactory.getCurrentSession().createCriteria(AdpeAccount.class);
        Criteria subCriteria1 = primaryAaCriteria.createCriteria("primaryCustodian");
        subCriteria1.add(Restrictions.eq("id", user.getId()));
//        DetachedCriteria primaryCrit = DetachedCriteria.forClass(AdpeAccount.class);
//        DetachedCriteria subCrit1 = primaryCrit.createCriteria("primaryCustodian");
//        subCrit1.add(Restrictions.eq("id", user.getId()));

        List<AdpeAccount> list1 = (List<AdpeAccount>) primaryAaCriteria.list();

        Criteria alternateAaCriteria = sessionFactory.getCurrentSession().createCriteria(AdpeAccount.class);
        Criteria subCriteria2 = alternateAaCriteria.createCriteria("alternateCustodians");
        subCriteria2.add(Restrictions.eq("id", user.getId()));

        List<AdpeAccount> list2 = (List<AdpeAccount>) alternateAaCriteria.list();

//        DetachedCriteria altCrit = DetachedCriteria.forClass(AdpeAccount.class);
//        DetachedCriteria subcrit2 = altCrit.createCriteria("alternateCustodians");
//        subcrit2.add(Restrictions.eq("id", user.getId()));
//
//        List<AdpeAccount> list2 = (List<AdpeAccount>) getHibernateTemplate().findByCriteria(altCrit);
        // combine the two lists, then subtract the duplicates (as defined by list2)
        List<AdpeAccount> results = ListUtils.subtract(ListUtils.intersection(list1, list2), list2);
        return results;

//        Set<AdpeAccount> transientSet = new HashSet<AdpeAccount>();
//        transientSet.addAll(list1);
//        transientSet.addAll(list2);
//
//        List<AdpeAccount> resultList = new ArrayList<AdpeAccount>();
//        resultList.addAll(transientSet);
//
//        return resultList;

    }

}
